package com.earthea.scaffold.system.service;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.crypto.SecureUtil;
import com.earthea.common.util.CompressionUtils;
import com.earthea.scaffold.common.entity.BaseDataRsp;
import com.earthea.scaffold.common.enums.BusinessTypeEnum;
import com.earthea.scaffold.common.enums.CommonStatusEnum;
import com.earthea.scaffold.common.enums.HttpCodeEnum;
import com.earthea.scaffold.common.exception.ServiceException;
import com.earthea.scaffold.common.service.BaseService;
import com.earthea.scaffold.common.util.ServletUtils;
import com.earthea.scaffold.domain.FileRelation;
import com.earthea.scaffold.domain.SysFile;
import com.earthea.scaffold.mapper.FileRelationMapper;
import com.earthea.scaffold.mapper.SysFileMapper;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * 文件Service业务层处理
 *
 * @author zhysunny
 * @date 2025-09-22
 */
@Slf4j
@Service
public class SysFileService extends BaseService<SysFile, SysFileMapper> {
    @Autowired
    private FileRelationMapper fileRelationMapper;

    @Value("${app.web.resourcePath}")
    private String resourcePath;

    @PostConstruct
    public void init() {
        File resourcePath = new File(this.resourcePath);
        if (!resourcePath.isDirectory()) {
            resourcePath.mkdirs();
        }
    }

    /**
     * 上传文件，同时关联业务
     *
     * @param businessId   业务iD
     * @param businessType 业务类型
     * @param file         文件
     * @return 结果
     */
    public BaseDataRsp<SysFile> upload(Long businessId, BusinessTypeEnum businessType, MultipartFile file) {
        BaseDataRsp<SysFile> rsp = upload(file, CommonStatusEnum.NORMAL);
        if (rsp.isSuccess()) {
            // 写入映射关系表
            FileRelation fileRelation = new FileRelation();
            fileRelation.setBusinessId(businessId);
            fileRelation.setBusinessType(businessType);
            fileRelation.setFileId(rsp.getData().getFileId());
            if (fileRelationMapper.selectByUnique(fileRelation) == null) {
                fileRelationMapper.insert(fileRelation);
            } else {
                fileRelationMapper.update(fileRelation);
            }
        }
        return rsp;
    }

    /**
     * 只上传文件，默认状态为停用
     *
     * @param file   文件
     * @param status 状态
     * @return 结果
     */
    public BaseDataRsp<SysFile> upload(MultipartFile file, CommonStatusEnum status) {
        BaseDataRsp<SysFile> rsp = new BaseDataRsp<>();
        try (InputStream md5InputStream = file.getInputStream();
             InputStream typeInputStream = file.getInputStream()) {
            String fileMd5 = SecureUtil.md5(md5InputStream);
            SysFile sysFile = mapper.selectByUnique(fileMd5);
            if (sysFile == null) {
                // 没查到新增
                sysFile = new SysFile();
                sysFile.setStatus(status);
                sysFile.setFileMd5(fileMd5);
                sysFile.setFileType(FileTypeUtil.getType(typeInputStream));
                sysFile.setFileSize(file.getSize());
                String compressed = CompressionUtils.compress(file.getBytes());
                sysFile.setFileData(compressed);
                rsp = save(sysFile) ? rsp : new BaseDataRsp<>(HttpCodeEnum.FAIL);
            }
            rsp.setData(sysFile);
            // 写入本地文件
            File localFile = new File(resourcePath, sysFile.getFileName());
            if (!localFile.exists()) {
                file.transferTo(localFile);
            }
            return rsp;
        } catch (IOException e) {
            log.error("上传文件失败", e);
        }
        return new BaseDataRsp<>(HttpCodeEnum.FAIL);
    }

    /**
     * 下载文件
     *
     * @param response 响应
     * @param fileId   文件ID
     */
    public void download(HttpServletResponse response, Long fileId) {
        BaseDataRsp<SysFile> dataRsp = selectById(fileId);
        if (dataRsp.isSuccess()) {
            SysFile sysFile = dataRsp.getData();
            byte[] data = CompressionUtils.decompress(sysFile.getFileData());
            try {
                String fileName = sysFile.getFileName();
                ServletUtils.download(response, fileName, data);
            } catch (IOException e) {
                throw new ServiceException(e);
            }
        }
    }
}